#include <nxos.h>

NX_PRIVATE char * threadState[] = {
    "    INIT",
    "   READY",
    " RUNNING",
    " BLOCKED",
    "    EXIT",
};

NX_PRIVATE NX_Error GetThreadSnapshot()
{
    NX_Error err = NX_EOK;
    NX_SnapshotThread snapshotInfo;

    NX_Solt solt = NX_SnapshotCreate(NX_SNAPSHOT_THREAD, 0);
    if (solt == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("Create snapshot failed!");
        return err;
    }

    NX_Printf("     TID      PID   ON_CPU  CPU_AFF    STATE FIX_PRIO     PRIO     NAME\r\n");
    if ((err = NX_SnapshotFirst(solt, (void *)&snapshotInfo)) == NX_EOK)
    {
        do
        {
            NX_Printf("%8d %8d %8d %8d %s %8d %8d     %s\r\n", snapshotInfo.threadId, snapshotInfo.ownerProcessId,
                      snapshotInfo.onCore, snapshotInfo.coreAffinity,
                      threadState[snapshotInfo.state], snapshotInfo.fixedPriority, snapshotInfo.priority,
                      snapshotInfo.name);
        } while((err = NX_SnapshotNext(solt, (void *)&snapshotInfo)) == NX_EOK);
    }

    NX_SoltClose(solt);
    return NX_EOK;
}

NX_Error PowerBoxBuiltinMonitor(int argc, char *argv[], char * env)
{
    NX_MemInfo meminfo;
    NX_CpuInfo cpuinfo;
    NX_U32 cores;
    int i;
    
    int memfd = NX_FileOpen("/System/Device/meminfo", NX_FILE_RDONLY, 0);
    if (memfd < 0)
    {
        NX_Printf("open meminfo faild!\n");
        return NX_ERROR;
    }

    int cpufd = NX_FileOpen("/System/Device/cpuinfo", NX_FILE_RDONLY, 0);
    if (cpufd < 0)
    {
        NX_Printf("open cpuinfo faild!\n");
        return NX_ERROR;
    }

    /* get info from kernel */
    cores = 0;
    NX_FileIoctl(cpufd, NX_CPUINFO_GET_CORES, &cores);
    NX_FileRead(cpufd, &cpuinfo, cores * sizeof(NX_U32));

    NX_FileRead(memfd, &meminfo, sizeof(meminfo));

    NX_Printf("----------------------------------------------------------------------\n");
    NX_Printf(" NXOS Resource Monitor                            \n");
    NX_Printf("----------------------------------------------------------------------\n\n");

    for (i = 0; i < cores; i++)
    {
        NX_Printf("Core    %d\n", i);
        int per = cpuinfo.usage[i];
        NX_Printf("[\x1b[31m");
        int tens = (per + 1) / 2;
        int i = 0;
        for (i = 0; i < tens; i++)
        {
            NX_Printf("|");
        }
        for (; i < 50; i++)
        {
            NX_Printf(" ");
        }

        NX_Printf("\x1b[0m] %d%%\n", per);
        NX_Printf("\n");
    }

    NX_Printf("Memory\n");
    NX_Printf("Total :   %d MB\n", (meminfo.totalPage * meminfo.pageSize) / (1024 * 1024));
    NX_Printf("Free  :   %d MB\n", ((meminfo.totalPage - meminfo.usedPage) * meminfo.pageSize) /(1024 * 1024));
    NX_Size used = meminfo.usedPage * meminfo.pageSize;
    int usePer = (used * 100) / (meminfo.totalPage * meminfo.pageSize);
    NX_Printf("[\x1b[31m");
    int tens = (usePer + 1) / 2;

    for (i = 0; i < tens; i++)
    {
        NX_Printf("|");
    }
    for (; i < 50; i++)
    {
        NX_Printf(" ");
    }

    NX_Printf("\x1b[0m] %d%%\n", usePer);
    NX_Printf("\n");
    NX_Printf("----------------------------------------------------------------------\n");
    GetThreadSnapshot();
    NX_Printf("----------------------------------------------------------------------\n\n");

    NX_FileClose(memfd);
    NX_FileClose(cpufd);

    return NX_EOK;
}
